import { computed, defineComponent, onUnmounted, reactive, ref, watch, defineProps, PropType } from "vue";

export interface SideBySideProps {
    left?: any
    right?: any
}

export default defineComponent({
    name: 'SideBySide',
    props: {
        left: {type: Object as PropType<SideBySideProps['left']>, default: null},
        right: {type: Object as PropType<SideBySideProps['right']>, default: null}
    },
    setup (props: SideBySideProps, { slots }) {
        const split = ref(50);
        const wrap = ref<HTMLElement | null>(null);
        const store = reactive({
            dragging: false,
            x: NaN,
            y: NaN,
            deltaX: 0,
            deltaY: 0
        });

        watch(() => store.deltaX, () => {
            if (!wrap.value) return;
            const wrapRect = wrap.value.getBoundingClientRect();
            const currentSplit = split.value;
            let w = currentSplit + (store.deltaX / wrapRect.width * 100);
            w = Math.min(w, 100);
            w = Math.max(w, 0);
            split.value = w;
        });

        const onDragStart = (e: MouseEvent) => {
            if (typeof e.button === 'number' && e.button !== 0) return;

            store.dragging = true;
            store.x = e.clientX;
            store.y = e.clientY;

            document.addEventListener('mousemove', onDragMove);
            document.addEventListener('mouseup', onDragEnd);
        };

        const onDragMove = (e: MouseEvent) => {
            const deltaX = e.clientX - store.x;
            const deltaY = e.clientY - store.y;
            store.x = e.clientX;
            store.y = e.clientY;
            store.deltaX = deltaX;
            store.deltaY = deltaY;
        };

        const onDragEnd = (e: MouseEvent) => {
            store.dragging = false;
            document.removeEventListener('mousemove', onDragMove);
            document.removeEventListener('mouseup', onDragEnd);
            store.deltaX = 0;
            store.deltaY = 0;
        };

        const leftStyle = computed(() => ({
            'clip-path': `inset(0 ${100 - split.value}% 0 0)`
        }));

        const handlerStyle = computed(() => ({
            left: `${split.value}%`
        }));

        onUnmounted(() => {
            document.removeEventListener('mousemove', onDragMove);
            document.removeEventListener('mouseup', onDragEnd);
        });

        return () => <div class="cm-side-by-side" ref={wrap}>
            <div class="cm-sbs-right-panel">
                {props.right}
            </div>
            <div class="cm-sbs-left-panel" style={leftStyle.value}>
                {props.left}
            </div>
            <div class="cm-sbs-handler" style={handlerStyle.value} onMousedown={onDragStart}>
                <div class="cm-sbs-track">
                    <div class="cm-sbs-line" />
                    <div class="cm-sbs-line" />
                    <div class="cm-sbs-line" />
                </div>
            </div>
        </div>;
    }
});
